//MIT License
//
//Copyright(c) 2020 Goodman Tao
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files(the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions :
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.


#include <stdio.h>
#include <stdlib.h>

#include "../__include/_LB_1_MemoryManager.h"
#include "../__include/_LB_5_String.h"


int main(int argc, char** argv)
{
    __MEMS();

    String *str = __SNEW(String);
    String *str2 = __SNEW(String);
    String *str3 = __SNEW(String);
    String *str4 = __SNEW(String);

    str->Call(str, "Init2", "Good weather today.");
    str2->Call(str2, "Init", str);
    str3->Call(str3, "Init3", str2, 2, 10);
    str4->Call(str4, "Init4", "But bad mood....", 0, 11);
    //printf("str : %d, %s\n", str->Call(str , "Length")->_int, str->Call(str , "Inner")->_pvoid);
    //printf("str2: %d, %s\n", str2->Call(str2, "Length")->_int, str2->Call(str2, "Inner")->_pvoid);
    //printf("str3: %d, %s\n", str3->Call(str3, "Length")->_int, str3->Call(str3, "Inner")->_pvoid);
    //printf("str4: %d, %s\n", str4->Call(str4, "Length")->_int, str4->Call(str4, "Inner")->_pvoid);
    int len = str->Call(str, "Length")->_int;
    char *inner = str->Call(str, "Inner")->_pvoid;
    printf("str : %d, %s\n", len, inner);

    int len2 = str2->Call(str2, "Length")->_int;
    char *inner2 = str2->Call(str2, "Inner")->_pvoid;
    printf("str2: %d, %s\n", len2, inner2);

    int len3 = str3->Call(str3, "Length")->_int;
    char *inner3 = str3->Call(str3, "Inner")->_pvoid;
    printf("str3: %d, %s\n", len3, inner3);

    int len4 = str4->Call(str4, "Length")->_int;
    char *inner4 = str4->Call(str4, "Inner")->_pvoid;
    printf("str4: %d, %s\n", len4, inner4);

    /*************************************************************/

    printf("is str starts with str2 ? %s\n", (str->Call(str, "StartsWith", str2, true)->_bool ? "true" : "false"));
    printf("is str starts with <pointer> ? %s\n", (str->Call(str, "StartsWith2", inner2, false)->_bool ? "true" : "false"));
    printf("is str ends with str2 ? %s\n", (str->Call(str, "EndsWith", str2, true)->_bool ? "true" : "false"));
    printf("is str ends with \'today.\' ? %s\n", (str->Call(str, "EndsWith2", "today.", true)->_bool ? "true" : "false"));

    String* trim = __SNEW(String);
    trim->Call(trim, "Init2", "gOOD");
    printf("trim: %s\n", trim->Call(trim, "Inner")->_pvoid);
    String* stra = str->Call(str, "TrimStart", trim, true, false)->_pvoid; __MEMI(stra, stra->Destroy);
    printf("trimmed str: %s\n", stra->Call(stra, "Inner")->_pvoid);

    String* strb = str->Call(str, "TrimStart2", "gO", true, false)->_pvoid; __MEMI(strb, strb->Destroy);
    printf("trimmed str: %s\n", strb->Call(strb, "Inner")->_pvoid);

    String* strc = str->Call(str, "TrimStart3", "ogd", 3, false)->_pvoid; __MEMI(strc, strc->Destroy);
    printf("trimmed str: %s\n", strc->Call(strc, "Inner")->_pvoid);
    
    String* strd = str->Call(str, "TrimStart3", "odG", 3, false)->_pvoid; __MEMI(strd, strd->Destroy);
    printf("trimmed str: %s\n", strd->Call(strd, "Inner")->_pvoid);

    /********************************************************/
    trim->Call(trim, "Init2", "day.");
    String* stre = str->Call(str, "TrimEnd", trim, true, false)->_pvoid; __MEMI(stre, stre->Destroy);
    printf("trimmed str: %s\n", stre->Call(stre, "Inner")->_pvoid);

    String* strf = str->Call(str, "TrimEnd2", "ODAY.", true, false)->_pvoid; __MEMI(strf, strf->Destroy);
    printf("trimmed str: %s\n", strf->Call(strf, "Inner")->_pvoid);

    String* strg = str->Call(str, "TrimEnd3", "yt dro.a", 8, false)->_pvoid; __MEMI(strg, strg->Destroy);
    printf("trimmed str: %s\n", strg->Call(strg, "Inner")->_pvoid);

    str->Call(str, "InsertAt2", 0, "GGGaaabbb");
    printf("InsertAt2 0: %s\n", str->Call(str, "Inner")->_pvoid);
    str->Call(str, "Append2", "bbbaaaGGG");
    printf("Append2 : %s\n", str->Call(str, "Inner")->_pvoid);

    String* strh = str->Call(str, "Trim2", "GGG", true, false)->_pvoid; __MEMI(strh, strh->Destroy);
    printf("Trim2: %s\n", strh->Call(strh, "Inner")->_pvoid);

    String* stri = str->Call(str, "Trim3", "aG", 2, false)->_pvoid; __MEMI(stri, stri->Destroy);
    printf("Trim3: %s\n", stri->Call(stri, "Inner")->_pvoid);

    /***************************************************************/
    printf("str: %s\n", str->Call(str, "Inner")->_pvoid);
    str->Call(str, "Trim3", "abG", 3, true);
    printf("str: %s\n", str->Call(str, "Inner")->_pvoid);

    str->Call(str, "Replace4", "ood", "Bad", true, true);
    printf("Replace4 str: %s\n", str->Call(str, "Inner")->_pvoid);
    
    String* rplc = __SNEW(String);
    rplc->Call(rplc, "Init2", "to");
    String* strj = str->Call(str, "Replace2", rplc, "e", true, false)->_pvoid; __MEMI(strj, strj->Destroy);
    printf("Replace2 str: %s\n", strj->Call(strj, "Inner")->_pvoid);
    
    String* strk = str->Call(str, "Replace2", rplc, "YY", true, false)->_pvoid; __MEMI(strk, strk->Destroy);
    printf("Replace2 str: %s\n", strk->Call(strk, "Inner")->_pvoid);

    String* strl = str->Call(str, "Replace2", rplc, "yesto", true, false)->_pvoid; __MEMI(strl, strl->Destroy);
    printf("Replace2 str: %s\n", strl->Call(strl, "Inner")->_pvoid);

    String* strm = str->Call(str, "Replace5", 'B', 'b', true, false)->_pvoid; __MEMI(strm, strm->Destroy);
    printf("Replace5 str: %s\n", strm->Call(strm, "Inner")->_pvoid);

    /**********************************************************************/
    String* strn = str->Call(str, "Substring", 4, 12, false)->_pvoid; __MEMI(strn, strn->Destroy);
    printf("Substring str: |%s|\n", strn->Call(strn, "Inner")->_pvoid);

    str->Call(str, "Remove", 18, 19);
    printf("Remove str: %s\n", str->Call(str, "Inner")->_pvoid);
    
    __CommonReturns* ret = str->Call(str, "Split2", " ", true, false);
    String** stro = ret->_pvoid;
    int stroLen = ret->_int;
    for (int i = 0; i < stroLen; i++) __MEMI(stro[i], stro[i]->Destroy);//!!!!!
    __MEMI(stro, free);//!!!!!
    for (int i = 0; i < stroLen; i++)
    {
        printf("stro[%d]: %s\n", i, stro[i]->Call(stro[i], "Inner")->_pvoid);
    }
    /*__CommonReturns **/ret = str->Call(str, "Split2", " ", true, true);
    String** strp = ret->_pvoid;
    int strpLen = ret->_int;
    for (int i = 0; i < strpLen; i++) __MEMI(strp[i], strp[i]->Destroy);//!!!
    __MEMI(strp, free);//!!!
    for (int i = 0; i < strpLen; i++)
    {
        printf("strp[%d]: %s\n", i, strp[i]->Call(strp[i], "Inner")->_pvoid);
    }

    /***********************************************************/
    String* str5 = __SNEW(String);
    str5->Call(str5, "Init2", "huifa");
    str5->Call(str5, "PadLeft", 8, '0');
    printf("PadLeft \'0\' -> 8: %s\n", str5->Call(str5, "Inner")->_pvoid);

    str5->Call(str5, "PadRight", 16, '1');
    printf("PadLeft \'1\' -> 16: %s\n", str5->Call(str5, "Inner")->_pvoid);

    String* strq = str->Call(str, "Substring", 4, 11, false)->_pvoid; __MEMI(strq, strq->Destroy);
    int idx = str->Call(str, "IndexOf2", strq, true, 0)->_int;
    printf("indexof %s is %d.\n", strq->Call(strq, "Inner")->_pvoid, idx);

    /************************************************************************/
    int idx2 = str->Call(str, "LastIndexOf", strq, true)->_int;
    printf("last index of %s is %d\n", strq->Call(strq, "Inner")->_pvoid, idx2);

    int eql = str->Call(str, "Equals", str, true)->_int;
    printf("is equal? %s\n", eql == 0 ? "true" : "false");

    String *upper = str->Call(str, "ToUpperCase", false)->_pvoid; __MEMI(upper, upper->Destroy);
    printf("upper: %s\n", upper->Call(upper, "Inner")->_pvoid);
    String *lower = str->Call(str, "ToLowerCase", false)->_pvoid; __MEMI(lower, lower->Destroy);
    printf("lower: %s\n", lower->Call(lower, "Inner")->_pvoid);

    /***************************************************************/
    String *uplow = __STATIC(String)->Concat1(upper, lower); __MEMI(uplow, uplow->Destroy);
    printf("uplow: %s\n", uplow->Call(uplow, "Inner")->_pvoid);

    String *uplowup = __STATIC(String)->Concat6(2, uplow, upper); __MEMI(uplowup, uplowup->Destroy);
    printf("uplowup: %s\n", uplowup->Call(uplowup, "Inner")->_pvoid);

    String *joinup = __STATIC(String)->Join2("||W||", 3, upper, upper, upper); __MEMI(joinup, joinup->Destroy);
    printf("joinup: %s\n", joinup->Call(joinup, "Inner")->_pvoid);

    int cmprIgnrCs = __STATIC(String)->Compare1(upper, lower, true);
    printf("compare ignore case: %s\n", cmprIgnrCs == 0 ? "equal" : "not equal");
    int cmpr = __STATIC(String)->Compare1(upper, lower, false);
    printf("compare: %s\n", cmpr == 0 ? "equal" : "not equal");

    __MEMT();
	return 0;
}
